using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using System.Threading;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Markup;
using System.Windows.Threading;

using MediaDesktopPlayerAddIn.Properties;
using ViewOnCore.Helper.WPF;
using ViewOnCore.Helper.Collection;
using ViewOnCore.HostContract.Media;
using ViewOnCore.Device;
using ViewOnCore.HostContract;

using Infragistics.Windows.DataPresenter;

namespace UI.Control
{
    public enum VideoLibraryDialogViewType
    {
        Details,
        Thumbnails
    }

    public partial class VideoLibraryDialog : System.Windows.Controls.UserControl
    {

        #region Variables

        //---- Lists
        private CollectionViewSource _sourceCVS;

        //---- The root folder for the library
        private MediaFolder _rootFolder;

        //----
        internal MediaDesktopPlayerAddIn.MediaDesktopPlayer MediaDesktopPlayer;
        private bool _isLoaded = false;
        private bool _showAsDesktopIcon;

        private MediaFolder _currentFolder = null;

        //---- Drag & drop
        private XamDataGridDragManager<MediaData> _dragManager;

        //----
        private VideoLibraryDialogViewType _viewType = VideoLibraryDialogViewType.Details;

        //---- TreeView edition
        private TreeViewItem _contextMenuItem;
        private TreeViewItem _editingMenuItem;
        private TextBox _editableHeader;
        private StackPanel _normalHeader;

        #endregion

        #region Constructor

        public VideoLibraryDialog(MediaDesktopPlayerAddIn.MediaDesktopPlayer mediaDesktopPlayerAddIn, MediaFolder folder)
        {
            InitializeComponent();
            MediaDesktopPlayer = mediaDesktopPlayerAddIn;
            _rootFolder = folder;
            _currentFolder = _rootFolder;

            childWindowDecorator.MediaData = folder;
            childWindowDecorator.Key = GenerateWindowKey();

            //---- Set up the main grid
            _sourceCVS = (CollectionViewSource)FindResource("VideoViewContentDataSource");

            //---- Track changes
            Host.MediaService.MediaDataOperation += new MediaDataOperationEventHandler(MediaKernel_MediasOperation);

            //---- Set up
            btnFolderAdd.IsEnabled = false;
            btnFolderUp.IsEnabled = false;
            btnRemove.IsEnabled = false;

            // Default view
            btnViewDetails.IsChecked = true;

            childWindowDecorator.VisuallyReady += new EventHandler(childWindowDecorator_VisuallyReady);

            btnImport.Click += new RoutedEventHandler(btnImport_Click);
            btnFolderUp.Click += new RoutedEventHandler(btnFolderUp_Click);
            btnFolderAdd.Click += new RoutedEventHandler(btnFolderAdd_Click);
            btnRemove.Click += new RoutedEventHandler(btnRemove_Click);
            btnViewDetails.Click += new RoutedEventHandler(btnViewDetails_Click);
            btnViewImages.Click += new RoutedEventHandler(btnViewImages_Click);
            btnRename.Click += new RoutedEventHandler(btnRename_Click);

            txtSearch.KeyDown += new KeyEventHandler(txtSearch_KeyDown);
            btnSearch.Click += new RoutedEventHandler(btnSearch_Click);

            tvFolders.SelectedItemChanged += new RoutedPropertyChangedEventHandler<object>(tvFolders_SelectedItemChanged);
            tvFolders.AddHandler(TreeViewItem.PreviewMouseRightButtonDownEvent, new MouseButtonEventHandler(treeView_MouseRightButtonDown));

            tvFolders.MouseMove += new MouseEventHandler(tvFolders_MouseMove);
            tvFolders.DragOver += new DragEventHandler(tvFolders_DragOver);
            tvFolders.Drop += new DragEventHandler(tvFolders_Drop);

            gridSplitter.PreviewMouseLeftButtonUp += new MouseButtonEventHandler(gridSplitter_PreviewMouseLeftButtonUp);

            xdgMedias.MouseDoubleClick += new MouseButtonEventHandler(xdgMedias_MouseDoubleClick);
            xdgMedias.SelectedItemsChanged += new EventHandler<Infragistics.Windows.DataPresenter.Events.SelectedItemsChangedEventArgs>(xdgMedias_SelectedItemsChanged);
            xdgMedias.EditModeEnding += new EventHandler<Infragistics.Windows.DataPresenter.Events.EditModeEndingEventArgs>(xdgMedias_EditModeEnding);
            xdgMedias.KeyUp += new KeyEventHandler(xdgMedias_KeyUp);
            xdgMedias.PreviewMouseRightButtonDown += new MouseButtonEventHandler(xdgMedias_PreviewMouseRightButtonDown);

            childWindowDecorator.MiniModeActivated += new EventHandler(childWindowDecorator_MiniModeActivated);

            //---- Rename
            if (folder != null)
                folder.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(folder_PropertyChanged);

            //---- Drag & drop
            _dragManager = new XamDataGridDragManager<MediaData>(xdgMedias);
            xdgMedias.AllowDrop = true;
            xdgMedias.Drop += new DragEventHandler(xdgMedias_Drop);
            xdgMedias.DragOver += new DragEventHandler(xdgMedias_DragOver);

            //---- Context menu
            ContextMenu menu = (ContextMenu)FindResource("VideoContextMenuVideo");
            ((MenuItem)menu.Items[0]).Click += new RoutedEventHandler(contextMenuPlay_Click);
            ((MenuItem)menu.Items[1]).Click += new RoutedEventHandler(contextMenuRemove_Click);
            ((MenuItem)menu.Items[2]).Click += new RoutedEventHandler(contextMenuRename_Click);
            ((MenuItem)menu.Items[4]).Click += new RoutedEventHandler(contextMenuSendToVideoPlayer_Click);

            menu = (ContextMenu)FindResource("VideoContextMenuFolder");
            ((MenuItem)menu.Items[0]).Click += new RoutedEventHandler(contextMenuOpenFolder_Click);
            ((MenuItem)menu.Items[1]).Click += new RoutedEventHandler(contextMenuOpenFolderAsLibrary_Click);
            ((MenuItem)menu.Items[2]).Click += new RoutedEventHandler(contextMenuRemove_Click);
            ((MenuItem)menu.Items[3]).Click += new RoutedEventHandler(contextMenuRename_Click);

            menu = (ContextMenu)FindResource("VideoContextMenuMultiples");
            ((MenuItem)menu.Items[0]).Click += new RoutedEventHandler(contextMenuRemove_Click);
        }

        void childWindowDecorator_VisuallyReady(object sender, EventArgs e)
        {
            btnFolderAdd.IsEnabled = true;

            if (_isLoaded)
                return;
            _isLoaded = true;

            //---- Set the correct mode
            if (childWindowDecorator.GenericProperties.ContainsKey("ViewType"))
                if (childWindowDecorator.GenericProperties["ViewType"] == VideoLibraryDialogViewType.Thumbnails.ToString())
                    btnViewImages_Click(null, null);

            InitializeFoldersTree();

            if (childWindowDecorator.GenericProperties.ContainsKey("SplitterPosition"))
                griSplittable.ColumnDefinitions[0].Width = new GridLength(Double.Parse(childWindowDecorator.GenericProperties["SplitterPosition"]));

            //---- Open the folder
            OpenFolder(_rootFolder);
        }

        private string GenerateWindowKey()
        {
            if (_rootFolder == null)
                return "Video$Library";

            string name = "";
            MediaFolder currentFolder = _rootFolder;
            while (currentFolder != null)
            {
                if (name.Length < 1)
                    name += currentFolder.Title.Replace(' ', '%');
                else
                    name = currentFolder.Title.Replace(' ', '%') + "$" + name;

                currentFolder = currentFolder.ParentFolder;
            }

            name = "Video" + "$" + name;

            return name;
        }

        private void InitializeFoldersTree()
        {
            InitializeFolder(null, _rootFolder);
        }

        private void InitializeFolder(TreeViewItem tvItem, MediaFolder folder)
        {
            TreeViewItem tvNewItem = CreateFolderTreeViewItem(tvItem, folder);

            //---- Sub folders
            ExtObservableCollection<MediaData> medias;

            if (folder == null)
                medias = Host.MediaService.CurrentMediaDeviceFeature.MediaDatas;
            else
                medias = folder.MediaDatas;

            foreach (MediaData mediaData in medias)
                if (mediaData is MediaFolder)
                    InitializeFolder(tvNewItem, (MediaFolder)mediaData);
        }

        #endregion

        #region CreateFolderTreeViewItem

        private TreeViewItem CreateFolderTreeViewItem(TreeViewItem parentTreeViewItem, MediaFolder folder)
        {
            TreeViewItem item = new TreeViewItem();
            item.Style = (Style)FindResource("TreeViewItem.TransparentWithEffect4");

            if (parentTreeViewItem == null)
                tvFolders.Items.Add(item);
            else
                parentTreeViewItem.Items.Add(item);

            //---- Header
            StackPanel stackPanel = new StackPanel();
            item.Header = stackPanel;
            stackPanel.Orientation = Orientation.Horizontal;
            Icon icon = new Icon();
            icon.Source = new BitmapImage(new Uri("pack://application:,,,/_images/PartVideo/folder.png"));
            icon.Width = 18;
            icon.Height = 18;
            stackPanel.Children.Add(icon);

            TextBlock textBlock = new TextBlock();
            textBlock.VerticalAlignment = VerticalAlignment.Center;
            textBlock.Margin = new Thickness(2, 0, 0, 0);
            stackPanel.Children.Add(textBlock);
            if (folder == null)
                textBlock.Text = Globalization.VideoLibraryDialog_Library;
            else
                textBlock.Text = folder.Title;

            //---- Context menu
            item.ContextMenu = new ContextMenu();
            item.ContextMenu.Items.Add(new MenuItem());
            item.ContextMenu.Items.Add(new MenuItem());
            if (folder == null || folder.Equals(_rootFolder))
            {
                ((MenuItem)item.ContextMenu.Items[0]).Header = Globalization.VideoLibraryDialog_ContextMenu_OpenFolderAsLibrary;
                ((MenuItem)item.ContextMenu.Items[1]).Header = Globalization.VideoLibraryDialog_ContextMenu_NewFolder;

                ((MenuItem)item.ContextMenu.Items[0]).Click += new RoutedEventHandler(OpenFolderAsLibrary_Click);
                ((MenuItem)item.ContextMenu.Items[1]).Click += new RoutedEventHandler(NewFolder_Click);
            }
            else
            {
                item.ContextMenu.Items.Add(new MenuItem());
                item.ContextMenu.Items.Add(new MenuItem());

                ((MenuItem)item.ContextMenu.Items[0]).Header = Globalization.VideoLibraryDialog_ContextMenu_RemoveFolder;
                ((MenuItem)item.ContextMenu.Items[1]).Header = Globalization.VideoLibraryDialog_ContextMenu_OpenFolderAsLibrary;
                ((MenuItem)item.ContextMenu.Items[2]).Header = Globalization.VideoLibraryDialog_ContextMenu_RenameFolder;
                ((MenuItem)item.ContextMenu.Items[3]).Header = Globalization.VideoLibraryDialog_ContextMenu_NewFolder;

                ((MenuItem)item.ContextMenu.Items[0]).Click += new RoutedEventHandler(RemoveFolder_Click);
                ((MenuItem)item.ContextMenu.Items[1]).Click += new RoutedEventHandler(OpenFolderAsLibrary_Click);
                ((MenuItem)item.ContextMenu.Items[2]).Click += new RoutedEventHandler(RenameFolder_Click);
                ((MenuItem)item.ContextMenu.Items[3]).Click += new RoutedEventHandler(NewFolder_Click);
            }

            //---- Set the tag
            item.Tag = folder;

            return item;
        }

        private TreeViewItem CreateHierarchicalFolderTreeViewItem(TreeViewItem parentTreeViewItem, MediaFolder folder)
        {
            TreeViewItem tvItem = CreateFolderTreeViewItem(parentTreeViewItem, folder);
            foreach (MediaData mediaData in folder.MediaDatas)
                if (mediaData is MediaFolder)
                    CreateHierarchicalFolderTreeViewItem(tvItem, (MediaFolder)mediaData);

            return tvItem;
        }

        #endregion

        #region Properties

        public MediaFolder RootFolder
        {
            get
            {
                return _rootFolder;
            }
        }

        #endregion

        #region Event : mini mode button

        void childWindowDecorator_MiniModeActivated(object sender, EventArgs e)
        {
            childWindowDecorator.SetAsDesktopIcon();
            childWindowDecorator.UpdateXml();
        }

        #endregion

        #region Tree : Events

        private int _lockTvFolderSelection = 0;

        void tvFolders_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            if (_lockTvFolderSelection > 0)
                return;

            MediaFolder folder = ((TreeViewItem)e.NewValue).Tag as MediaFolder;
            OpenFolder(folder);
        }

        #endregion

        #region Tree : Contextual Menu

        void RemoveFolder_Click(object sender, RoutedEventArgs e)
        {
            Tree_RemoveSelection();
        }

        void RenameFolder_Click(object sender, RoutedEventArgs e)
        {
            Tree_RenameSelection();
        }

        void NewFolder_Click(object sender, RoutedEventArgs e)
        {
            Tree_NewFolder();
        }

        void OpenFolderAsLibrary_Click(object sender, RoutedEventArgs e)
        {
            Tree_OpenSelectionAsLibrary();
        }

        #endregion

        #region Grid splitter : events

        void gridSplitter_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            childWindowDecorator.GenericProperties["SplitterPosition"] = griSplittable.ColumnDefinitions[0].Width.Value.ToString();
            childWindowDecorator.UpdateXml();
        }

        #endregion

        #region Grid : ContextMenu

        void xdgMedias_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;

            if (xdgMedias.SelectedItems.Records.Count < 1)
                return;

            Video video = ((DataRecord)xdgMedias.SelectedItems.Records[0]).DataItem as Video;
            MediaFolder folder = ((DataRecord)xdgMedias.SelectedItems.Records[0]).DataItem as MediaFolder;

            ContextMenu menu = null;
            if (xdgMedias.SelectedItems.Records.Count == 1)
            {
                if (video != null)
                    menu = (ContextMenu)FindResource("VideoContextMenuVideo");

                if (folder != null)
                    menu = (ContextMenu)FindResource("VideoContextMenuFolder");
            }
            else if (xdgMedias.SelectedItems.Records.Count > 1)
                menu = (ContextMenu)FindResource("VideoContextMenuMultiples");

            menu.IsOpen = true;
            e.Handled = true;
        }

        void contextMenuPlay_Click(object sender, RoutedEventArgs e)
        {
            if (xdgMedias.SelectedItems.Records.Count < 1)
                return;

            Host.MediaService.PlayMedia(((DataRecord)xdgMedias.SelectedItems.Records[0]).DataItem as Video);
        }

        void contextMenuRemove_Click(object sender, RoutedEventArgs e)
        {
            Grid_RemoveSelection();
        }

        void contextMenuRename_Click(object sender, RoutedEventArgs e)
        {
            Grid_RenameSelection();
        }

        void contextMenuSendToVideoPlayer_Click(object sender, RoutedEventArgs e)
        {
            if (xdgMedias.SelectedItems.Records.Count < 1)
                return;

            Video video = ((DataRecord)xdgMedias.SelectedItems.Records[0]).DataItem as Video;
            SendToVideoPlayer(video);
        }

        void contextMenuOpenFolder_Click(object sender, RoutedEventArgs e)
        {
            Grid_OpenSelectedFolder();
        }

        void contextMenuOpenFolderAsLibrary_Click(object sender, RoutedEventArgs e)
        {
            Grid_OpenSelectionAsLibrary();
        }

        #endregion

        #region Grid : Change of view

        void btnViewImages_Click(object sender, RoutedEventArgs e)
        {
            _viewType = VideoLibraryDialogViewType.Thumbnails;

            btnViewDetails.IsChecked = false;

            xdgMedias.View = (Infragistics.Windows.DataPresenter.ViewBase)FindResource("ThumbnailsView");

            ResourceDictionary resourceDictionary = new ResourceDictionary();
            resourceDictionary.Source = new Uri("/MediaDesktopPlayerAddIn;component/UI/Control/videolibrary/views/ThumbnailDataRecordPresenter.xaml", UriKind.Relative);
            xdgMedias.Resources.MergedDictionaries.Add(resourceDictionary);

            childWindowDecorator.GenericProperties["ViewType"] = _viewType.ToString();
            childWindowDecorator.UpdateXml();
        }

        void btnViewDetails_Click(object sender, RoutedEventArgs e)
        {
            _viewType = VideoLibraryDialogViewType.Details;

            btnViewImages.IsChecked = false;

            xdgMedias.View = (Infragistics.Windows.DataPresenter.ViewBase)FindResource("DetailsView");

            childWindowDecorator.GenericProperties["ViewType"] = _viewType.ToString();
            childWindowDecorator.UpdateXml();
        }

        #endregion

        #region Grid : Double click - play / Open folder

        void xdgMedias_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            PlaySelectedVideo();
            Grid_OpenSelectedFolder();
        }

        #endregion

        #region Grid : Selection changed

        void xdgMedias_SelectedItemsChanged(object sender, Infragistics.Windows.DataPresenter.Events.SelectedItemsChangedEventArgs e)
        {
            UpdateToolbarState();

            //---- Update the tags info
            List<Video> selectedVideos = new List<Video>(xdgMedias.SelectedItems.Records.Count);
            foreach (Record record in xdgMedias.SelectedItems.Records)
                if (((DataRecord)record).DataItem is Video)
                    selectedVideos.Add(((DataRecord)record).DataItem as Video);

            MediaDesktopPlayer.RefreshTag(selectedVideos);
        }

        private void UpdateToolbarState()
        {
            if (xdgMedias.SelectedItems.Records.Count == 0)
            {
                btnRemove.IsEnabled = false;
                btnRename.IsEnabled = false;
                return;
            }

            if (xdgMedias.SelectedItems.Records.Count == 1)
            {
                btnRemove.IsEnabled = true;
                btnRename.IsEnabled = true;
                return;
            }

            btnRemove.IsEnabled = true;
            btnRename.IsEnabled = false;

            //---- Up button
            if (_rootFolder == null)
            {
                if (_currentFolder == null)
                    btnFolderUp.IsEnabled = false;
                else
                    btnFolderUp.IsEnabled = true;
            }
            else
            {
                if (_currentFolder.Equals(_rootFolder))
                    btnFolderUp.IsEnabled = false;
                else
                    btnFolderUp.IsEnabled = true;
            }
        }

        #endregion

        #region SendToVideoPlayer

        void SendToVideoPlayer(Video video)
        {
            // Pause all the videos
            MediaDesktopPlayer.StandByAllVideos();

            // Send the command
            Host.SendCommand(this, HostCommandIds.PlayMediaData, video);
        }

        #endregion

        #region Event : Associated folder is renamed

        void folder_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            childWindowDecorator.Key = GenerateWindowKey();
        }

        #endregion

        #region PlaySelectedVideo

        private void PlaySelectedVideo()
        {
            if (xdgMedias.SelectedItems.Records.Count < 1)
                return;

            Video video = ((DataRecord)xdgMedias.SelectedItems.Records[0]).DataItem as Video;

            if (video == null)
                return;

            Host.MediaService.PlayMedia(video);
        }

        #endregion

        #region OpenFolder

        private void OpenFolder(MediaFolder folder)
        {
            _currentFolder = folder;

            ExtObservableCollection<MediaData> medias;

            if (folder == null)
                medias = Host.MediaService.CurrentMediaDeviceFeature.MediaDatas;
            else
                medias = folder.MediaDatas;

            //---- Sort
            medias.Sort(new VideoFeatureItemComparer());

            //---- Update UI
            btnFolderUp.IsEnabled = (folder != _rootFolder);

            //---- Change the content
            _sourceCVS.Source = medias; //new EnumerableWrapperForInfragisticsBugFix(medias);

            //---- Update the navigation location
            string navigationLocation = "";
            MediaFolder currentFolder = folder;
            while (currentFolder != null)
            {
                if (navigationLocation.Length < 1)
                    navigationLocation = currentFolder.Title;
                else
                    navigationLocation = currentFolder.Title + " > " + navigationLocation;

                currentFolder = currentFolder.ParentFolder;
            }

            txtNavigation.Text = navigationLocation;

            //---- Update the tree view
            tvFolders.SelectedItemChanged -= new RoutedPropertyChangedEventHandler<object>(tvFolders_SelectedItemChanged);
            SelectTreeViewItem(tvFolders.Items, folder);
            tvFolders.SelectedItemChanged += new RoutedPropertyChangedEventHandler<object>(tvFolders_SelectedItemChanged);

            //---- Unselect all
            xdgMedias.SelectedItems.Records.Clear();

            //---- Update the toolbar state
            UpdateToolbarState();
        }

        private bool SelectTreeViewItem(ItemCollection items, MediaFolder folder)
        {
            foreach (TreeViewItem item in items)
            {
                if (item.Tag == null && folder == null)
                {
                    item.IsSelected = true;
                    return true;
                }
                else if (item.Tag != null && item.Tag.Equals(folder))
                {
                    item.IsSelected = true;
                    return true;
                }

                if (SelectTreeViewItem(item.Items, folder))
                    return true;
            }

            return false;
        }

        #endregion

        #region Tool bar : Import

        void btnImport_Click(object sender, RoutedEventArgs e)
        {
            FolderBrowserDialog dialog = new FolderBrowserDialog();
            dialog.ShowDialog((Desktop)Host.ApplicationDesktop,
                                                new ChildWindowDialogClosedHandler(OnDialogClosed));
        }

        private void OnDialogClosed(ChildWindowDecorator window)
        {
            FolderBrowserDialog dialog = window.Parent as FolderBrowserDialog;

            if (!dialog.IsOk)
                return;

            Host.MediaService.ImportMediaDatas(_currentFolder, dialog.SelectedPath);
        }

        #endregion

        #region Tool bar : Up

        void btnFolderUp_Click(object sender, RoutedEventArgs e)
        {
            OpenFolder(_currentFolder.ParentFolder);
        }

        #endregion

        #region Tool bar : Add folder

        void btnFolderAdd_Click(object sender, RoutedEventArgs e)
        {
            Grid_NewFolder();
        }

        #endregion

        #region Tool bar : Remove

        void btnRemove_Click(object sender, RoutedEventArgs e)
        {
            Grid_RemoveSelection();
        }

        #endregion

        #region Tool bar : Rename

        void btnRename_Click(object sender, RoutedEventArgs e)
        {
            Grid_RenameSelection();
        }

        #endregion

        #region Drag & Drop

        static private TreeView _dragDropTreeView;

        void tvFolders_MouseMove(object sender, MouseEventArgs e)
        {
            // During tree view edition
            if (_normalHeader != null)
                return;

            if (e.LeftButton == MouseButtonState.Pressed &&
                ((TreeViewItem)tvFolders.SelectedValue).Tag != null) // Cannot drop the Root
            {
                _dragDropTreeView = tvFolders;
                DragDrop.DoDragDrop(tvFolders, ((TreeViewItem)tvFolders.SelectedValue).Tag, DragDropEffects.All | DragDropEffects.Link);
            }
        }

        void tvFolders_DragOver(object sender, DragEventArgs e)
        {
            HandleDragOver(sender, e);
        }

        void tvFolders_Drop(object sender, DragEventArgs e)
        {
            if (!HandleDragOver(sender, e))
                return;

            //---- Source
            MediaFolder sourceFolder = e.Data.GetData(typeof(MediaFolder).FullName) as MediaFolder;
            if (sourceFolder == null)
                return;

            //---- Target
            Point mousePosition = MouseUtilities.GetMousePosition(tvFolders);
            TreeViewItem item = TreeViewHelper.GetTreeViewItemAtLocation(tvFolders, mousePosition) as TreeViewItem;
            MediaFolder targetFolder = item.Tag as MediaFolder;

            //---- Move the folder
            Host.MediaService.CurrentMediaDeviceFeature.MoveMediaFolder(sourceFolder, targetFolder);
        }

        private bool HandleDragOver(object sender, DragEventArgs e)
        {
            e.Handled = true;
            e.Effects = DragDropEffects.None;

            //---- Source
            if (e.Data.GetFormats().Length < 1)
                return false;

            if (_dragDropTreeView == null || !_dragDropTreeView.Equals(tvFolders))
                return false;

            MediaFolder sourceFolder = e.Data.GetData(typeof(MediaFolder).FullName) as MediaFolder;
            if (sourceFolder == null)
                return false;

            //---- Target
            Point mousePosition = MouseUtilities.GetMousePosition(tvFolders);
            TreeViewItem item = TreeViewHelper.GetTreeViewItemAtLocation(tvFolders, mousePosition) as TreeViewItem;

            if (item == null)
            {
                e.Effects = DragDropEffects.Move;
                return false;
            }

            MediaFolder targetFolder = item.Tag as MediaFolder;

            //---- Check if it is the 'Library'
            if (targetFolder == null)
            {
                if (sourceFolder.ParentFolder == null)
                    e.Effects = DragDropEffects.None;
                else
                {
                    e.Effects = DragDropEffects.Copy;
                    return true;
                }

                return false;
            }

            //---- Check if it is not the parent folder
            if (targetFolder.Equals(sourceFolder.ParentFolder))
            {
                e.Effects = DragDropEffects.None;
                return false;
            }

            //---- Check if it is not the same folder
            if (sourceFolder.Equals(targetFolder))
            {
                e.Effects = DragDropEffects.None;
                return false;
            }

            //---- Check if the target is not a child
            if (IsChildFolder(sourceFolder, targetFolder))
            {
                e.Effects = DragDropEffects.None;
                return false;
            }

            e.Effects = DragDropEffects.Copy;
            return true;
        }

        private bool IsChildFolder(MediaFolder sourceFolder, MediaFolder targetFolder)
        {
            foreach (MediaData mediaData in sourceFolder.MediaDatas)
                if (mediaData is MediaFolder)
                {
                    if (mediaData.Equals(targetFolder))
                        return true;

                    if (IsChildFolder((MediaFolder)mediaData, targetFolder))
                        return true;
                }

            return false;
        }

        #endregion

        #region Search

        void btnSearch_Click(object sender, RoutedEventArgs e)
        {
            StartSearch();
        }

        void txtSearch_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
                StartSearch();
        }

        private void StartSearch()
        {
            // Refresh filter
            _sourceCVS.Filter -= new FilterEventHandler(sourceCVS_FilterSearch);
            _sourceCVS.Filter += new FilterEventHandler(sourceCVS_FilterSearch);

            //---- Update the toolbar state
            UpdateToolbarState();
        }

        void sourceCVS_FilterSearch(object sender, FilterEventArgs e)
        {
            string text = txtSearch.Text.ToLower().Trim();

            if (text.Length < 1)
                return;

            Video video = e.Item as Video;
            MediaFolder folder = e.Item as MediaFolder;

            if (video != null)
            {
                if (!video.FormattedGenres.ToLower().Contains(text) &&
                    !video.Title.ToLower().Contains(text) &&
                    !video.FormattedCasts.ToLower().Contains(text) &&
                    !video.FormattedMetaTags.ToLower().Contains(text))
                    e.Accepted = false;
            }
            else if (folder != null)
            {
                if (!folder.Title.ToLower().Contains(text))
                    e.Accepted = false;
            }
        }

        #endregion

        #region Grid_OpenSelectedFolder

        private void Grid_OpenSelectedFolder()
        {
            if (xdgMedias.SelectedItems.Records.Count < 1)
                return;

            MediaFolder folder = ((DataRecord)xdgMedias.SelectedItems.Records[0]).DataItem as MediaFolder;

            if (folder == null)
                return;

            OpenFolder(folder);
        }

        #endregion

        #region Grid_NewFolder

        private void Grid_NewFolder()
        {
            //---- Search for unique name
            string name = "Noname";
            int index = 0;

            while (Host.MediaService.CurrentMediaDeviceFeature.FindMediaFolder(_currentFolder, name) != null)
            {
                index++;
                name = "Noname " + index;
            }

            //---- Add the folder
            MediaFolder folder = new MediaFolder(name);

            Host.MediaService.CurrentMediaDeviceFeature.AddMediaData(_currentFolder, folder, true);

            //---- Rename
            xdgMedias.SelectedItems.Records.Clear();

            if (xdgMedias.ScrollInfo != null)
                xdgMedias.ScrollInfo.SetVerticalOffset(1);

            xdgMedias.Records[xdgMedias.Records.Count - 1].IsSelected = true;

            Grid_RenameSelection();
        }

        #endregion

        #region Tree_NewFolder

        private void Tree_NewFolder()
        {
            MediaFeature feature = Host.MediaService.CurrentMediaDeviceFeature;

            //---- Search for unique name
            string name = "Noname";
            int index = 0;

            MediaFolder currentFolder = _contextMenuItem.Tag as MediaFolder;

            while (feature.FindMediaFolder(currentFolder, name) != null)
            {
                index++;
                name = "Noname " + index;
            }

            //---- Add the folder
            MediaFolder folder = new MediaFolder(name);

            feature.AddMediaData(currentFolder, folder, true);

            //---- Rename
            TreeViewItem tvItem = TreeViewHelper.SearchTreeViewItem(tvFolders.Items, folder);
            tvItem.IsSelected = true;

            StartTreeEditing(tvItem);
        }

        #endregion

        #region Grid_RemoveSelection

        private void Grid_RemoveSelection()
        {
            if (xdgMedias.SelectedItems.Records.Count < 1)
                return;

            string message = Globalization.VideoPart_RemoveSelection_Message1;
            string message2 = Globalization.VideoPart_RemoveSelection_Message2;

            QuestionDialog dialog = new QuestionDialog(QuestionDialog.QuestionDialogType.YesNo, message, message2, null, null, 350);
            dialog.ShowDialog(Host.ApplicationDesktop,
                                                new ChildWindowDialogClosedHandler(Grid_RemoveSelectionOnDialogClosed));
        }

        private void Grid_RemoveSelectionOnDialogClosed(ChildWindowDecorator window)
        {
            QuestionDialog dialog = window.Parent as QuestionDialog;

            if (!dialog.IsOkYes)
                return;

            //---- Remove the desktop icons / windows
            foreach (DataRecord record in xdgMedias.SelectedItems.Records)
            {
                DesktopIcon icon = childWindowDecorator.Desktop.FindDesktopIcon(record.DataItem as MediaData);
                if (icon != null)
                    icon.Close();
            }

            //---- Remove
            List<MediaData> medias = new List<MediaData>();
            foreach (DataRecord record in xdgMedias.SelectedItems.Records)
                medias.Add(record.DataItem as MediaData);

            Host.MediaService.RemoveMediaDatas(medias, Host.MediaService.CurrentMediaDeviceFeature, Host.MediaService.CurrentMediaDeviceFeatureItem, _currentFolder);

            btnRemove.IsEnabled = false;

            //---- Update the toolbar state
            UpdateToolbarState();
        }

        #endregion

        #region Tree_RemoveSelection

        private void Tree_RemoveSelection()
        {
            if (tvFolders.SelectedItem == null)
                return;

            string message = Globalization.VideoPart_RemoveSelection_Message1;
            string message2 = Globalization.VideoPart_RemoveSelection_Message2;

            QuestionDialog dialog = new QuestionDialog(QuestionDialog.QuestionDialogType.YesNo, message, message2, null, null, 350);
            dialog.ShowDialog(Host.ApplicationDesktop,
                                                new ChildWindowDialogClosedHandler(Tree_RemoveSelectionOnDialogClosed));
        }

        private void Tree_RemoveSelectionOnDialogClosed(ChildWindowDecorator window)
        {
            QuestionDialog dialog = window.Parent as QuestionDialog;

            if (!dialog.IsOkYes)
                return;

            //---- Remove the desktop icons / windows
            DesktopIcon icon = childWindowDecorator.Desktop.FindDesktopIcon(((TreeViewItem)tvFolders.SelectedItem).Tag as MediaData);
            if (icon != null)
                icon.Close();

            //---- Remove
            List<MediaData> medias = new List<MediaData>();
            MediaFolder folder = ((TreeViewItem)tvFolders.SelectedItem).Tag as MediaFolder;
            medias.Add(folder);

            Host.MediaService.RemoveMediaDatas(medias, Host.MediaService.CurrentMediaDeviceFeature, Host.MediaService.CurrentMediaDeviceFeatureItem, folder.ParentFolder);

            btnRemove.IsEnabled = false;

            //---- Update the toolbar state
            UpdateToolbarState();
        }

        #endregion

        #region Grid_RenameSelection

        private void Grid_RenameSelection()
        {
            if (_viewType == VideoLibraryDialogViewType.Details)
            {
                xdgMedias.ActiveCell = ((DataRecord)xdgMedias.SelectedItems.Records[0]).Cells[1];

                xdgMedias.FieldLayouts[0].Fields["Title"].Settings.AllowEdit = true;
                xdgMedias.ExecuteCommand(DataPresenterCommands.StartEditMode);
            }
            else
            {
                VideoThumbnail.RequestEdit(xdgMedias, this);
            }
        }

        private void xdgMedias_EditModeEnding(object sender, Infragistics.Windows.DataPresenter.Events.EditModeEndingEventArgs e)
        {
            xdgMedias.FieldLayouts[0].Fields["Title"].Settings.AllowEdit = false;

            if (!OnEditModeEnding(e.Editor.Text, (DataRecord)e.Cell.Record))
            {
                e.AcceptChanges = false;
                e.Cancel = true;
                return;
            }

            // We handle the change in "UpdateMediaDatas"
            e.AcceptChanges = false;
        }

        internal bool OnEditModeEnding(string text, DataRecord dataRecord)
        {
            if (text.Trim().Length < 1)
                return false;

            if (text.Contains("%") || text.Contains("$"))
                return false;

            MediaData media = dataRecord.DataItem as MediaData;

            List<MediaData> mediasToUpdate = new List<MediaData>();
            mediasToUpdate.Add(media);

            Host.MediaService.UpdateMediaDatas(mediasToUpdate, Host.MediaService.CurrentMediaDeviceFeature, MediaDataTagField.Title, text);

            return true;
        }

        #endregion

        #region Tree_RenameSelection

        private void Tree_RenameSelection()
        {
            StartTreeEditing(_contextMenuItem);
        }

        #endregion

        #region Grid_OpenSelectionAsLibrary

        private void Grid_OpenSelectionAsLibrary()
        {
            if (xdgMedias.SelectedItems.Records.Count < 1)
                return;

            MediaFolder folder = ((DataRecord)xdgMedias.SelectedItems.Records[0]).DataItem as MediaFolder;

            if (folder == null)
                return;

            VideoLibraryDialog dialog = MediaDesktopPlayer.FindVideoLibraryDialog(folder);

            //---- Bring it to top
            if (dialog != null)
            {
                dialog.childWindowDecorator.BringToTop();
                return;
            }

            //---- Create it
            dialog = MediaDesktopPlayer.CreateLibraryDialog(folder, ChildWindowDecoratorState.Opened, new Point(10, 10));

            MediaDesktopPlayer.ShowLibraryDialog(dialog);

            dialog.childWindowDecorator.UpdateXml();
        }

        #endregion

        #region Tree_OpenSelectionAsLibrary

        private void Tree_OpenSelectionAsLibrary()
        {
            if (tvFolders.SelectedItem == null)
                return;

            MediaFolder folder = ((TreeViewItem)tvFolders.SelectedItem).Tag as MediaFolder;

            if (folder == null)
                return;

            VideoLibraryDialog dialog = MediaDesktopPlayer.FindVideoLibraryDialog(folder);

            //---- Bring it to top
            if (dialog != null)
            {
                dialog.childWindowDecorator.BringToTop();
                return;
            }

            //---- Create it
            dialog = MediaDesktopPlayer.CreateLibraryDialog(folder, ChildWindowDecoratorState.Opened, new Point(10, 10));

            MediaDesktopPlayer.ShowLibraryDialog(dialog);

            dialog.childWindowDecorator.UpdateXml();
        }

        #endregion

        #region Tree : edition

        private void StartTreeEditing(TreeViewItem editingMenuItem)
        {
            if (_normalHeader != null)
                StopTreeEditing(true); // Stop with the previous editing node

            // Now use the new node
            _editingMenuItem = editingMenuItem;

            TextBox txtEditor = new TextBox();
            txtEditor.Text = ((MediaFolder)_editingMenuItem.Tag).Title;
            txtEditor.KeyDown += new KeyEventHandler(txtEditor_KeyDown);
            txtEditor.LostFocus += new RoutedEventHandler(txtEditor_LostFocus);

            _normalHeader = (StackPanel)_editingMenuItem.Header;
            _editingMenuItem.Header = txtEditor;

            // Get focus and get all
            txtEditor.UpdateLayout(); // Needed !! refresh the IsVisible property
            txtEditor.SelectAll();
            txtEditor.Focus();
        }

        private void StopTreeEditing(bool validate)
        {
            if (_editingMenuItem == null)
                return;

            if (!(_editingMenuItem.Tag is MediaFolder))
                return;

            TextBox txtEditor = (TextBox)_editingMenuItem.Header;
            txtEditor.KeyDown -= new KeyEventHandler(txtEditor_KeyDown);
            txtEditor.LostFocus -= new RoutedEventHandler(txtEditor_LostFocus);

            try
            {
                if (validate)
                {
                    //----
                    if (txtEditor.Text.Trim().Length < 1)
                        return;

                    if (txtEditor.Text.Contains("%") || txtEditor.Text.Contains("$"))
                        return;

                    ((TextBlock)_normalHeader.Children[1]).Text = txtEditor.Text;

                    MediaData media = (MediaData)_editingMenuItem.Tag;

                    List<MediaData> mediasToUpdate = new List<MediaData>();
                    mediasToUpdate.Add(media);

                    Host.MediaService.UpdateMediaDatas(mediasToUpdate, Host.MediaService.CurrentMediaDeviceFeature, MediaDataTagField.Title, txtEditor.Text);
                }
            }
            finally
            {
                _editingMenuItem.Header = _normalHeader;
                _normalHeader = null;
                _editingMenuItem = null;
            }
        }

        void treeView_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (e != null)
                _contextMenuItem = TreeViewHelper.SearchAncestorTreeViewItem(e.Source);
        }

        void treeView_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (e.ClickCount != 2)
                return;

            _contextMenuItem = TreeViewHelper.GetTreeViewItemFromChild(e.OriginalSource as DependencyObject);
            if (_contextMenuItem == null)
                return;

            if ((_contextMenuItem.Tag as MediaFolder) == null)
                return;

            StartTreeEditing(_contextMenuItem);
        }

        void txtEditor_LostFocus(object sender, RoutedEventArgs e)
        {
            StopTreeEditing(true);
        }

        void txtEditor_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
                StopTreeEditing(true);
            else if (e.Key == Key.Escape)
                StopTreeEditing(false);
        }

        #endregion

        #region Keyboard : Remove

        void xdgMedias_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key != Key.Delete)
                return;

            if (tvFolders.IsKeyboardFocused)
                Tree_RemoveSelection();
            else
                Grid_RemoveSelection();
        }

        #endregion

        #region Drop file on list

        void xdgMedias_DragOver(object sender, DragEventArgs e)
        {
            string[] filePathInfo = e.Data.GetData("FileDrop", true) as string[];
            if (filePathInfo == null)
            {
                e.Handled = true;
                e.Effects = DragDropEffects.None;
                return;
            }

            foreach (string filePath in filePathInfo)
            {
                if (!Host.MediaService.IsSupportedVideoFile(filePathInfo[0]))
                {
                    e.Handled = true;
                    e.Effects = DragDropEffects.None;
                    return;
                }
            }

            e.Effects = DragDropEffects.Copy;
        }

        void xdgMedias_Drop(object sender, DragEventArgs e)
        {
            string[] filePathInfo = e.Data.GetData("FileDrop", true) as string[];
            if (filePathInfo == null)
                return;

            foreach (string filePath in filePathInfo)
            {
                if (!Host.MediaService.IsSupportedVideoFile(filePath))
                    continue;

                //---- Import the file
                Video media = Video.FromFile(filePath);

                if (Host.MediaService.CurrentMediaDeviceFeature.CanImport(_currentFolder, media))
                    Host.MediaService.CurrentMediaDeviceFeature.AddMediaData(_currentFolder, media, false);
            }

            //---- Save the changes
            Host.MediaService.CurrentMediaDevice.OnSaveChanges();
            Host.MediaService.NotifyMediaDataOperation(Host.MediaService.CurrentMediaDeviceFeature, null, MediaOperationKind.Imported, null);
        }

        #endregion

        #region Media Kernel : Medias operations

        void MediaKernel_MediasOperation(MediaFeature feature, MediaItem featureItem, MediaOperationKind operationKind, List<MediaData> medias)
        {
            if (feature.Handle != "MediaDesktop")
                return;

            Dispatcher.Invoke(DispatcherPriority.Normal,
                (DelegateInvoker)delegate
                {
                    OnMediasOperation(feature, featureItem, operationKind, medias);
                });
        }

        private void OnMediasOperation(MediaFeature feature, MediaItem featureItem, MediaOperationKind operationKind, List<MediaData> medias)
        {
            //---- Added
            if (operationKind == MediaOperationKind.Added)
            {
                // We can only add one folder at a time
                if (medias.Count != 1)
                    return;

                MediaFolder folder = medias[0] as MediaFolder;
                if (folder == null)
                    return;

                TreeViewItem tvParent = TreeViewHelper.SearchTreeViewItem(tvFolders.Items, folder.ParentFolder);

                if (tvParent == null)
                    return;

                TreeViewItem tvNewItem = CreateFolderTreeViewItem(tvParent, folder);
                return;
            }

            //---- Removed
            if (operationKind == MediaOperationKind.Removed)
            {
                foreach (MediaData mediaData in medias)
                {
                    MediaFolder folder = mediaData as MediaFolder;

                    if (folder == null)
                        continue;

                    // Do not remove the library !
                    if (folder.Equals(_rootFolder))
                    {
                        this.childWindowDecorator.Close();
                        return;
                    }
                    else
                    {
                        TreeViewItem tvItem = TreeViewHelper.SearchTreeViewItem(tvFolders.Items, folder);

                        if (tvItem == null)
                            return;

                        if (tvItem.Parent == null || !(tvItem.Parent is TreeViewItem))
                            tvFolders.Items.Remove(tvItem);
                        else
                            ((TreeViewItem)tvItem.Parent).Items.Remove(tvItem);
                    }
                }

                return;
            }

            //---- Rename
            if (operationKind == MediaOperationKind.Updated)
            {
                // We can only rename one folder at a time
                if (medias.Count != 1)
                    return;

                MediaFolder folder = medias[0] as MediaFolder;
                if (folder == null)
                    return;

                //-- Create a new key for the window (Can be updated due to root position/name change)
                childWindowDecorator.Key = GenerateWindowKey();

                //-- Update the tree view item
                TreeViewItem tvItem = TreeViewHelper.SearchTreeViewItem(tvFolders.Items, folder);

                if (tvItem == null)
                    return;

                ((TextBlock)((StackPanel)tvItem.Header).Children[1]).Text = folder.Title;

                return;
            }

            //---- Moved
            if (operationKind == MediaOperationKind.Moved)
            {
                MediaFolder sourceFolder = medias[0] as MediaFolder;
                MediaFolder targetFolder = medias[1] as MediaFolder;

                //-- Tree
                TreeViewItem sourceTvItem = TreeViewHelper.SearchTreeViewItem(tvFolders.Items, sourceFolder);
                TreeViewItem targetTvItem = TreeViewHelper.SearchTreeViewItem(tvFolders.Items, targetFolder);

                // Create the item
                if (sourceTvItem == null)
                {
                    TreeViewItem parentTvItem = TreeViewHelper.SearchTreeViewItem(tvFolders.Items, sourceFolder.ParentFolder);
                    if (parentTvItem != null)
                        sourceTvItem = CreateHierarchicalFolderTreeViewItem(parentTvItem, sourceFolder);
                }

                if (sourceTvItem != null)
                {
                    _lockTvFolderSelection++;
                    sourceTvItem.IsSelected = false;

                    if (sourceTvItem.Parent is TreeViewItem)
                        ((TreeViewItem)sourceTvItem.Parent).Items.Remove(sourceTvItem);

                    if (targetTvItem != null)
                    {
                        targetTvItem.Items.Add(sourceTvItem);
                        sourceTvItem.IsSelected = false;
                    }
                    _lockTvFolderSelection--;
                }

                //-- Grid

                //-- Create a new key for the window (Can be updated due to root position)
                childWindowDecorator.Key = GenerateWindowKey();
            }
        }

        #endregion

    }

}